<?php
/**
 * Here is your custom functions.
 */


function removeSpaces($str)
{
    return preg_replace('/\s+/', '', $str);
}

function removeColons($str)
{
    return preg_replace('/[:：\s]/u', '', $str);
}


function cleanInvalidUtf8($text)
{
    // 检测编码并转换为 UTF-8
//    $text = mb_convert_encoding($text, 'UTF-8', 'auto');

    // 移除非法字符
    $text = preg_replace('/[\x00-\x1F\x7F]/u', '', $text);

    // 移除 BOM
    $text = preg_replace("/^\xEF\xBB\xBF/", '', $text);

    return batchReplaceGarbled(str_replace("聽", "", $text));
}

function batchReplaceGarbled($input)
{
    static $garbledMap = [
        '鍔ㄦ极' => '动漫',
        '聽鍔ㄦ极' => '动漫',
        '鍔ㄥ极' => '动漫',
        '缁艰壓' => '综艺'

        // 添加更多乱码映射
    ];

    if (is_array($input)) {
        return array_map(__FUNCTION__, $input);
    }

    if (!is_string($input)) {
        return $input;
    }

    foreach ($garbledMap as $garbled => $correct) {
        $input = str_replace($garbled, $correct, $input);
    }

    return $input;
}

function getString($str)
{
    $encoding = mb_detect_encoding($str, ['UTF-8', 'GB2312', 'GBK', 'BIG5', 'ISO-8859-1']);
    if ($encoding !== 'UTF-8') {
        $str = mb_convert_encoding($str, 'UTF-8', $encoding);
    }
    return $str;
}

function extractHashFromHtml($html)
{
    // 匹配 Hash: 后面的40位十六进制字符
    $pattern = '/Hash:\s*([a-fA-F0-9]{40})/';
    if (preg_match($pattern, $html, $matches)) {
        return $matches[1];
    }
    return null;
}

function getMediaInfo($filePath)
{
    // 检查文件是否存在
    if (!file_exists($filePath)) {
        throw new Exception("文件不存在: " . $filePath);
    }

    // 对于 TS 文件，使用完整扫描模式
    $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
    
    // 调用 mediainfo 命令，增加参数确保完整扫描
    // --Full 参数会扫描整个文件，对 TS 文件特别重要
    // --Language=raw 输出原始数据
    if (in_array($extension, ['ts', 'm2ts', 'mts'])) {
        $command = 'mediainfo --Full "' . $filePath . '"';
    } else {
        $command = 'mediainfo "' . $filePath . '"';
    }

    $output = shell_exec($command);

    // 如果 mediainfo 无法获取视频信息，尝试使用 ffprobe 作为备用方案
    if (empty($output) || (strpos($output, 'Video') === false && in_array($extension, ['ts', 'm2ts', 'mts', 'mp4', 'mkv', 'avi']))) {
        addlog('getMediaInfo', "mediainfo 未获取到视频信息，尝试使用 ffprobe: " . $filePath);
        
        // 检查 ffprobe 是否可用
        if (isFfprobeAvailable()) {
            // 使用 ffprobe 获取信息
            $ffprobeCommand = 'ffprobe -v quiet -print_format json -show_format -show_streams "' . $filePath . '"';
            $ffprobeOutput = shell_exec($ffprobeCommand);
            
            if (!empty($ffprobeOutput)) {
                $ffprobeData = json_decode($ffprobeOutput, true);
                if (isset($ffprobeData['streams'])) {
                    // 将 ffprobe 输出转换为类似 mediainfo 的格式
                    $output = convertFfprobeToMediaInfo($ffprobeData, $filePath);
                    addlog('getMediaInfo', "成功使用 ffprobe 获取信息");
                }
            }
        } else {
            addlog('getMediaInfo', "ffprobe 不可用，无法获取视频信息", 'warning');
        }
    }

    return $output;
}

/**
 * 检查 ffprobe 是否可用
 */
function isFfprobeAvailable()
{
    static $available = null;
    
    // 使用静态变量缓存结果，避免重复检查
    if ($available !== null) {
        return $available;
    }
    
    // Windows 系统
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        $command = 'where ffprobe 2>nul';
    } else {
        // Linux/Unix 系统
        $command = 'which ffprobe 2>/dev/null';
    }
    
    $output = shell_exec($command);
    $available = !empty($output);
    
    return $available;
}

/**
 * 将 ffprobe 的 JSON 输出转换为类似 mediainfo 的文本格式
 */
function convertFfprobeToMediaInfo($ffprobeData, $filePath)
{
    $output = "General\n";
    
    if (isset($ffprobeData['format'])) {
        $format = $ffprobeData['format'];
        $output .= "Complete name                            : " . basename($filePath) . "\n";
        $output .= "Format                                   : " . ($format['format_name'] ?? 'Unknown') . "\n";
        
        if (isset($format['size'])) {
            $output .= "File size                                : " . formatBytes($format['size']) . "\n";
        }
        
        if (isset($format['duration'])) {
            $output .= "Duration                                 : " . formatDuration($format['duration']) . "\n";
        }
        
        if (isset($format['bit_rate'])) {
            $output .= "Overall bit rate                         : " . formatBitrate($format['bit_rate']) . "\n";
        }
    }
    
    // 处理视频流
    $videoIndex = 1;
    $audioIndex = 1;
    
    if (isset($ffprobeData['streams'])) {
        foreach ($ffprobeData['streams'] as $stream) {
            if ($stream['codec_type'] === 'video') {
                $output .= "\nVideo\n";
                $output .= "ID                                       : " . ($stream['index'] + 1) . "\n";
                $output .= "Format                                   : " . getVideoFormatName($stream['codec_name'] ?? 'Unknown') . "\n";
                
                if (isset($stream['width']) && isset($stream['height'])) {
                    $output .= "Width                                    : " . number_format($stream['width']) . " pixels\n";
                    $output .= "Height                                   : " . number_format($stream['height']) . " pixels\n";
                }
                
                if (isset($stream['display_aspect_ratio'])) {
                    $output .= "Display aspect ratio                     : " . $stream['display_aspect_ratio'] . "\n";
                }
                
                if (isset($stream['r_frame_rate'])) {
                    $output .= "Frame rate                               : " . $stream['r_frame_rate'] . " FPS\n";
                }
                
                if (isset($stream['bit_rate'])) {
                    $output .= "Bit rate                                 : " . formatBitrate($stream['bit_rate']) . "\n";
                }
                
                $videoIndex++;
            } elseif ($stream['codec_type'] === 'audio') {
                $output .= "\nAudio #" . $audioIndex . "\n";
                $output .= "ID                                       : " . ($stream['index'] + 1) . "\n";
                $output .= "Format                                   : " . getAudioFormatName($stream['codec_name'] ?? 'Unknown') . "\n";
                
                if (isset($stream['channels'])) {
                    $output .= "Channel(s)                               : " . $stream['channels'] . " channels\n";
                }
                
                if (isset($stream['sample_rate'])) {
                    $output .= "Sampling rate                            : " . ($stream['sample_rate'] / 1000) . " kHz\n";
                }
                
                if (isset($stream['bit_rate'])) {
                    $output .= "Bit rate                                 : " . formatBitrate($stream['bit_rate']) . "\n";
                }
                
                $audioIndex++;
            }
        }
    }
    
    return $output;
}

// 辅助函数
function formatBytes($bytes)
{
    $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
    for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
        $bytes /= 1024;
    }
    return round($bytes, 2) . " " . $units[$i];
}

function convertToGB($value)
{
    // 去除空格并统一转为小写
    $value = trim(strtolower($value));

    // 提取数字部分
    $number = floatval(preg_replace('/[^\d.]/', '', $value));

    // 获取单位
    $unit = preg_replace('/[\d.\s]/', '', $value);

    // 根据单位转换为GB
    switch ($unit) {
        case 'tb':
            return $number * 1024;  // 1 TB = 1024 GB
        case 'gb':
            return $number;
        case 'mb':
            return $number / 1024;  // 1 GB = 1024 MB
        default:
            return $number;  // 默认认为是GB
    }
}


function formatDuration($seconds)
{
    $hours = floor($seconds / 3600);
    $minutes = floor(($seconds % 3600) / 60);
    $secs = $seconds % 60;

    if ($hours > 0) {
        return sprintf("%d h %d min", $hours, $minutes);
    } else {
        return sprintf("%d min %d sec", $minutes, $secs);
    }
}

function formatBitrate($bitrate)
{
    if ($bitrate) {
        return number_format($bitrate / 1000, 0) . " kb/s";
    }
    return "N/A";
}

function getVideoFormatName($codec)
{
    $formats = [
        'hevc' => 'HEVC',
        'h264' => 'AVC',
        'vp9' => 'VP9',
        'av1' => 'AV1'
    ];
    return $formats[$codec] ?? strtoupper($codec);
}

function getAudioFormatName($codec)
{
    $formats = [
        'aac' => 'AAC LC',
        'mp3' => 'MPEG Audio',
        'ac3' => 'AC-3',
        'dts' => 'DTS'
    ];
    return $formats[$codec] ?? strtoupper($codec);
}

function calculateAspectRatio($width, $height)
{
    // 简单的宽高比计算
    if ($height > 0) {
        $ratio = $width / $height;
        if (abs($ratio - 2.40) < 0.05) return "2.40:1";
        if (abs($ratio - 2.35) < 0.05) return "2.35:1";
        if (abs($ratio - 1.78) < 0.05) return "16:9";
        if (abs($ratio - 1.33) < 0.05) return "4:3";
        return number_format($ratio, 2) . ":1";
    }
    return "N/A";
}


function getImdbUrl($htmlContent)
{
    $pattern = '/https:\/\/www\.imdb\.com\/title\/[a-zA-Z0-9]+(?=\/)/';
    if (preg_match($pattern, $htmlContent, $matches)) {
        // 由于正则表达式不包含末尾斜杠，直接使用匹配结果
        $imdbLink = $matches[0];
        return $imdbLink;
    }
    return '';
}

function getPTGen($htmlContent)
{
    // 定义按优先级顺序的链接类型和对应的正则表达式
    $linkPatterns = [
        'douban' => '/https:\/\/movie\.douban\.com\/subject\/[0-9]+\//',
        'imdb' => '/https:\/\/www\.imdb\.com\/title\/[a-zA-Z0-9]+\//',
        'bangumi' => '/https:\/\/bgm\.tv\/subject\/[0-9]+/',
        'indienova' => '/https:\/\/indienova\.com\/game\/[a-zA-Z0-9\-]+/'
    ];
    // 按顺序查找链接
    $foundLink = null;
    $foundType = null;
    foreach ($linkPatterns as $type => $pattern) {
        if (preg_match($pattern, $htmlContent, $matches)) {
            // 移除末尾的斜杠（如果有的话）
            $foundLink = rtrim($matches[0], '/');
            $foundType = $type;
            break; // 一旦找到就停止后续查找
        }
    }
    if ($foundLink) {
        return $foundLink;
    }
    return '';
}

function extractUrlParams($url)
{
    $parsedUrl = parse_url($url);
    if (isset($parsedUrl['query'])) {
        parse_str($parsedUrl['query'], $params);
        return $params;
    }
    return [];
}

function parseString($input)
{
    // 使用正则表达式匹配三个部分
    $pattern = '/\[-CSAUTO\],\s*\[-([^\]]+)\],\s*\[([^\]]+)\]/';
    preg_match($pattern, $input, $matches);

    if (count($matches) >= 3) {
        return [
            'site' => $matches[1],      // 站点信息
            'hash' => $matches[2]       // hash信息
        ];
    }

    return null; // 格式不匹配时返回null
}

function calculateTorrentHashWithBencode($torrentFilePath)
{
    // 读取torrent文件
    $torrentData = file_get_contents($torrentFilePath);
    // 解码
    $decoded = \SandFox\Bencode\Bencode::decode($torrentData);
    // 获取info部分并重新编码
    $infoEncoded = \SandFox\Bencode\Bencode::encode($decoded['info']);

    // 计算SHA1哈希
    $hash = sha1($infoEncoded, true);
    $hexHash = bin2hex($hash);

    return $hexHash;
}

function deleteFilesIfExists($fileList)
{
    $deleted = 0;
    foreach ($fileList as $file) {
        // 只有文件存在时才尝试删除
        if (file_exists($file) && is_file($file)) {
            if (unlink($file)) {
                $deleted++;
                echo "已删除: $file\n";
            } else {
                echo "删除失败: $file\n";
            }
        } else {
            echo "跳过 (不存在): $file\n";
        }
    }
    return $deleted;
}

function checkResourceTailImages($textContent, $minImages = 3)
{
    // 检查输入参数是否为null或空字符串
    if ($textContent === null || $textContent === '') {
        return ['isValid' => false, 'tailCount' => 0, 'message' => '输入内容为空'];
    }

    // 使用正则表达式匹配信息标记，支持可变空格
    $infoPattern = '/◎\s*[简主导编剧片集豆瓣IMDbTMDB].*?[介演员导编剧长长数链接]/';

    // 查找最后一个信息标记的位置
    preg_match_all($infoPattern, $textContent, $infoMatches, PREG_OFFSET_CAPTURE);

    $lastInfoPos = 0;
    if (!empty($infoMatches[0])) {
        $lastMatch = end($infoMatches[0]);
        $lastInfoPos = $lastMatch[1] + strlen($lastMatch[0]);
    }

    // 查找所有图片
    preg_match_all('/\[img\](.*?)\[\/img\]/i', $textContent, $imgMatches, PREG_OFFSET_CAPTURE);

    if (empty($imgMatches[0])) {
        return ['isValid' => false, 'tailCount' => 0, 'message' => '未找到任何图片'];
    }

    // 获取图床黑名单
    $banPictureBed = \plugin\csauto\app\service\SystemService::getConfig(\plugin\csauto\app\service\SystemService::BAN_PICTURE_BED);
    $banDomains = [];
    if (!empty($banPictureBed)) {
        $banDomains = array_map('trim', explode(',', $banPictureBed));
    }

    // 统计最后一个信息标记之后的图片
    $tailImages = [];
    foreach ($imgMatches[0] as $index => $imgMatch) {
        if ($imgMatch[1] > $lastInfoPos) {
            // 获取图片URL
            $imgUrl = isset($imgMatches[1][$index]) ? $imgMatches[1][$index][0] : '';
            
            // 检查URL是否在黑名单中
            $isBanned = false;
            foreach ($banDomains as $domain) {
                if (!empty($domain) && stripos($imgUrl, $domain) !== false) {
                    $isBanned = true;
                    break;
                }
            }
            
            // 只统计不在黑名单中的图片
            if (!$isBanned) {
                $tailImages[] = $imgMatch[0];
            }
        }
    }

    $tailCount = count($tailImages);

    return $tailCount;
}

function convertDataArrayToImgTags($dataArray)
{
    $imgTags = '';

    // 遍历data数组中的每个项目
    foreach ($dataArray as $item) {
        // 检查是否包含direct_url
        if (isset($item['direct_url'])) {
            // 生成img标签
            $imgTags .= "[img]" . $item['direct_url'] . "[/img]\n";
        }
    }

    // 移除末尾的换行符
    return $imgTags ? "\n" . rtrim($imgTags) : $imgTags;
}

function addlog($type, $data, $status = 'info')
{
    // 格式化日志消息
    $message = str_pad($type, 24, "=") . ">>>>>";
    
    // 如果data是数组，转换为字符串
    if (is_array($data)) {
        $message .= print_r($data, true);
    } else {
        $message .= $data;
    }
    
    // 判断是否需要写入日志文件（只有Debug相关的日志才写入文件）
    $needWriteFile = (stripos($type, 'Debug') !== false) ;
    
    if ($needWriteFile) {
        // 使用webman的Log系统写入日志文件（支持Docker环境）
        try {
            switch ($status) {
                case 'error':
                    \support\Log::error($message, ['channel' => 'plugin.csauto']);
                    break;
                case 'warning':
                    \support\Log::warning($message, ['channel' => 'plugin.csauto']);
                    break;
                case 'debug':
                    \support\Log::debug($message, ['channel' => 'plugin.csauto']);
                    break;
                case 'info':
                default:
                    \support\Log::info($message, ['channel' => 'plugin.csauto']);
                    break;
            }
        } catch (\Throwable $e) {
            // 如果Log系统失败，回退到echo输出
            echo date('Y-m-d H:i:s') . "->{$status}->" . $message . PHP_EOL;
        }
    }
    
    // 输出到标准输出（方便Docker logs查看）
    echo date('Y-m-d H:i:s') . "->{$status}->" . $message . PHP_EOL;
}

function getTorrentHash($torrentFilePath)
{
    // 读取torrent文件内容
    $torrentData = file_get_contents($torrentFilePath);
    // 解码Bencode数据
    $decodedData = \SandFox\Bencode\Bencode::decode($torrentData);
    // 获取info部分并重新编码
    $infoData = \SandFox\Bencode\Bencode::encode($decodedData['info']);

    // 计算SHA-1哈希值
    return sha1($infoData);
}

/**
 * 隐藏URL中的敏感信息（如passkey）
 * 
 * @param string $url 原始URL
 * @param int $hideLength 隐藏的字符长度，默认8位
 * @return string 脱敏后的URL
 */
function hideSensitiveUrl($url, $hideLength = 8)
{
    if (empty($url)) {
        return $url;
    }
    
    // 解析URL
    $parsedUrl = parse_url($url);
    
    // 如果没有查询字符串，直接返回
    if (!isset($parsedUrl['query'])) {
        return $url;
    }
    
    // 解析查询参数
    parse_str($parsedUrl['query'], $queryParams);
    
    // 处理 passkey 参数
    if (isset($queryParams['passkey']) && strlen($queryParams['passkey']) > $hideLength) {
        $passkey = $queryParams['passkey'];
        $visiblePart = substr($passkey, 0, -$hideLength);
        $queryParams['passkey'] = $visiblePart . str_repeat('*', $hideLength);
    }
    
    // 重建查询字符串
    $newQuery = http_build_query($queryParams);
    
    // 重建URL
    $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] . '://' : '';
    $host = isset($parsedUrl['host']) ? $parsedUrl['host'] : '';
    $port = isset($parsedUrl['port']) ? ':' . $parsedUrl['port'] : '';
    $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
    $query = $newQuery ? '?' . $newQuery : '';
    $fragment = isset($parsedUrl['fragment']) ? '#' . $parsedUrl['fragment'] : '';
    
    return $scheme . $host . $port . $path . $query . $fragment;
}